package com.deep.deepenterpise.dao.config;

import com.zaxxer.hikari.HikariDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.jetbrains.annotations.NotNull;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

import javax.annotation.Resource;
import javax.sql.DataSource;

@Configuration
@MapperScan(basePackages = "com.deep.deepenterpise.dao", sqlSessionFactoryRef = "drMysqlSqlSessionFactory")
public class DrMysqlDataSourceConfig {
    @Resource
    DrMysqlJdbcParamConfig drMysqlConfig;

    @Primary
    @Bean(name = "drMysqlDataSource")
    public DataSource drMysqlDataSource() {
        HikariDataSource drHikariDataSource = getHikariDataSource();

        // 数据库连接池性能优化
        drHikariDataSource.addDataSourceProperty("cachePrepStmts", true);
        drHikariDataSource.addDataSourceProperty("prepStmtCacheSize", 250);
        drHikariDataSource.addDataSourceProperty("prepStmtCacheSqlLimit", 2048);
        drHikariDataSource.addDataSourceProperty("useServerPrepStmts", true);

        // 其他性能优化
        drHikariDataSource.addDataSourceProperty("tcpNoDelay", true);
        drHikariDataSource.addDataSourceProperty("useLocalSessionState", true);
        drHikariDataSource.addDataSourceProperty("useLocalTransactionState", true);
        drHikariDataSource.addDataSourceProperty("rewriteBatchedStatements", true);
        drHikariDataSource.addDataSourceProperty("cacheResultSetMetadata", true);
        drHikariDataSource.addDataSourceProperty("cacheServerConfiguration", true);
        drHikariDataSource.addDataSourceProperty("elideSetAutoCommits", true);
        drHikariDataSource.addDataSourceProperty("maintainTimeStats", false);

        return drHikariDataSource;
    }

    @NotNull
    private HikariDataSource getHikariDataSource() {
        HikariDataSource drHikariDataSource = new HikariDataSource();
        drHikariDataSource.setJdbcUrl(drMysqlConfig.getUrl());
        drHikariDataSource.setUsername(drMysqlConfig.getUsername());
        drHikariDataSource.setPassword(drMysqlConfig.getPassword());
        drHikariDataSource.setDriverClassName(drMysqlConfig.getDriverClassName());
        // 连接池大小配置
        drHikariDataSource.setMaximumPoolSize(25);
        drHikariDataSource.setMinimumIdle(5);
        drHikariDataSource.setPoolName("drMysqlHikariCP");

        // 连接超时时间和空闲时间
        drHikariDataSource.setConnectionTimeout(30000);
        drHikariDataSource.setIdleTimeout(600000);

        // 连接心跳检测配置
        drHikariDataSource.setConnectionTestQuery("SELECT 1");
        return drHikariDataSource;
    }

    @Bean
    public PlatformTransactionManager drTransactionManager(@Qualifier("drMysqlDataSource") DataSource drDataSource) {
        return new DataSourceTransactionManager(drDataSource);
    }

    @Bean(name = "drMysqlSqlSessionFactory")
    public SqlSessionFactory drMysqlSqlSessionFactory(@Qualifier("drMysqlDataSource") DataSource drDataSource) throws Exception {
        SqlSessionFactoryBean drSessionFactoryBean = new SqlSessionFactoryBean();
        drSessionFactoryBean.setDataSource(drDataSource);
        drSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:DrMapper/**/*.xml"));
        drSessionFactoryBean.setConfigLocation(new PathMatchingResourcePatternResolver()
                .getResource("classpath:mybatis-config.xml"));
        return drSessionFactoryBean.getObject();
    }
}
